import Bullet from "./Bullet";
import Global, { Player } from "./Global";
import Utils from "./Utils";
import { Hero as LHero, Bullet as LBullet } from "./GameState";

const { ccclass, property } = cc._decorator;

@ccclass
export default class NewClass extends cc.Component {

    @property(cc.Sprite)
    bloodBar: cc.Sprite = null;

    mapRoot: cc.Node = null;
    player: cc.Node = null;
    weapon: cc.Node = null;
    bulletRoot: cc.Node = null;
    camera: cc.Node = null; //除了UI不动元素之外的摄像机

    //子弹节点的对象池
    bulletPool: cc.NodePool = null;
    bullets: Array<Bullet> = []; //所有当前玩家的子弹
    //武器射速（每秒射几次，例如5次，射速即为0.2)
    shootTime: number = 0.2;
    bulletPrefab: cc.Prefab = null;
    bNomalDegree: number = 90; //初始子弹角度
    isMoving: boolean = false;
    isShooting: boolean = false;
    rotateRadian: number = 0;
    moveRadian: number = 0;
    moveDegree: number = 0;
    walkTime: number = 0;
    totalTime: number = 0;
    timestamp: number;
    startPos: cc.Vec2;
    endPos: cc.Vec2;
    lastEndPos: cc.Vec2;
    vx; vy;
    preMoveRadian: number;
    nowMoveRadian: number;
    factors: any;
    hasNewPos: boolean = false;
    smoothing: boolean = false;

    //------ 坦克属性 ----//
    totalBlood: number = 0;
    teamId: string = null;
    isDie: boolean = false;
    playerId: string = null;
    moveSpeed: number = 0;
    blood: number = 0;
    damage: number = 0;
    defence: number = 0;
    lv: number = 0;


    initHero(player: Player) {
        this.player = this.node.getChildByName("player");
        this.weapon = this.node.getChildByName("weapon");
        this.camera = cc.find("Canvas/Main Camera");
        this.mapRoot = cc.find("Canvas/mapRoot");
        this.bulletRoot = cc.find("Canvas/mapRoot/bulletRoot");

        this.initHeroImg(1);
        this.initWeapon(1);
        this.initBulletPool(11);

        this.teamId = player.teamId;
        this.isDie = player.isDie;
        this.playerId = player.playerId;
        this.moveSpeed = player.moveSpeed;
        this.blood = player.blood;
        this.damage = player.damage;
        this.defence = player.defence;
        this.lv = player.lv;
        this.totalBlood = player.totalBlood;
        this.node.position = player.pos;

        //摄像头跟随人物
        if (this.playerId == MGOBE.Player.id) {
            this.camera.setPosition(this.node.position);
        }

    }

    onLoad() {

    }

    start() {

    }

    updatePosition(posX, posY, moveRadian) {
        this.preMoveRadian = this.moveRadian;
        this.moveRadian = moveRadian;
        this.setMoveRadian(moveRadian);

        this.endPos = cc.v2(posX, posY);
        this.startPos = this.node.getPosition();

        // cc.log(this.endPos)
        // cc.log(this.startPos)
        let dir = this.endPos.sub(this.startPos);
        let len = dir.mag();
        this.totalTime = len / this.moveSpeed;
        // cc.log(this.totalTime)
        this.walkTime = 0;
        // this.vx = this.moveSpeed * dir.x / len; // x轴方向的速度。
        // this.vy = this.moveSpeed * dir.y / len; // y轴方向的速度。

        // this.hasNewPos = true;
        // if (this.totalTime == 0) {
        //     this.hasNewPos = false;
        // }
        // this.smoothing = false;
    }

    linearLerp(t: number, start: cc.Vec2, end: cc.Vec2) {
        let sx = start.x;
        let sy = start.y;
        let ex = end.x;
        let ey = end.y;
        let px = this.doLerp(t, sx, ex);
        let py = this.doLerp(t, sy, ey);
        return cc.v2(px, py);
    }

    doLerp(t, start, end) {
        return (1 - t) * start + t * end;
    }

    getFactors(startPos: cc.Vec2, endPos: cc.Vec2, moveSpeed: number, smoveRadian: number, emoveRadian: number) {
        let x0 = startPos.x;
        let y0 = startPos.y;
        let x1 = startPos.x + moveSpeed * Math.cos(smoveRadian);
        let y1 = startPos.y + moveSpeed * Math.sin(smoveRadian);
        let x2 = endPos.x - moveSpeed * Math.cos(emoveRadian);
        let y2 = endPos.y - moveSpeed * Math.sin(emoveRadian);
        let x3 = endPos.x;
        let y3 = endPos.y;

        let A = x3 - x2 * 3 + x1 * 3 - x0;
        let B = x2 * 3 - x1 * 6 + x0 * 3;
        let C = x1 * 3 - x0 * 3;
        let D = x0;
        let E = y3 - y2 * 3 + y1 * 3 - y0;
        let F = x2 * 3 - y1 * 6 + y0 * 3;
        let G = y1 * 3 - y0 * 3;
        let H = y0;

        return { A, B, C, D, E, F, G, H };
    }

    smoothPosition(walkTime: number, totalTime: number, factors: any) {
        let A = factors.A;
        let B = factors.B;
        let C = factors.C;
        let D = factors.D;
        let E = factors.E;
        let F = factors.F;
        let G = factors.G;
        let H = factors.H;

        let t = 1;
        if (totalTime == 0 || walkTime == 0) {
            t = 0;
        } else if (walkTime >= totalTime) {
            t = 1;
        } else {
            t = Math.floor(walkTime / totalTime * 10000) / 10000;
        }

        let x = A * Math.pow(t, 3) + B * Math.pow(t, 2) + C * t + D;
        let y = E * Math.pow(t, 3) + F * Math.pow(t, 2) + G * t + H;

        return cc.v2(x, y);
    }

    update(dt) {
        if (!this.isMoving) {
            return;
        }

        let cPos = this.node.getPosition();
        if (this.startPos == this.endPos || this.walkTime >= this.totalTime) {
            return;
        }
        this.walkTime += dt;
        if (this.walkTime >= this.totalTime) {
            this.walkTime = this.totalTime;
        }
        // cPos = this.linearLerp(this.walkTime/this.totalTime,cPos,this.endPos);
        this.startPos.lerp(this.endPos, this.walkTime / this.totalTime, cPos);
        this.node.setPosition(cPos);

        //移动角色
        // this.node.x += this.moveSpeed * Math.cos(this.moveRadian) * dt;
        // this.node.y += this.moveSpeed * Math.sin(this.moveRadian) * dt;
        // cc.log(`人物位置:${this.node.position}`)

        // let cPos = this.node.getPosition();
        // if (this.hasNewPos) {
        //     if (!this.smoothing) {
        //         this.factors = this.getFactors(cPos, this.endPos, this.moveSpeed, this.preMoveRadian, this.moveRadian);
        //         this.smoothing = true;
        //         return;
        //     } else {
        //         this.walkTime += dt;
        //         if (this.walkTime >= this.totalTime) {
        //             this.hasNewPos = false;
        //             this.smoothing = false;
        //         }
        //         cPos = this.smoothPosition(this.walkTime,this.totalTime,this.factors);
        //     }
        // } else {
        //     cPos.x += this.moveSpeed * Math.cos(this.moveRadian) * dt;
        //     cPos.y += this.moveSpeed * Math.sin(this.moveRadian) * dt;
        // }
        // this.node.setPosition(cPos);

        //摄像头跟随人物
        if (this.playerId == MGOBE.Player.id) {
            this.camera.setPosition(this.node.position);
        }

    }

    /**
     * 更新血条
     */
    updateBlood(blood: number) {
        this.blood = blood;
        let percent = Math.floor((this.blood / this.totalBlood) * 1000)/1000;
        // cc.log(`当前血量:${blood}`)
        this.bloodBar.fillRange = percent;
    }

    /**
     * 初始化子弹池
     * @param index 
     */
    initBulletPool(index: number) {
        if (this.bulletPool) {
            this.bulletPool.clear();
        }
        this.bulletPool = new cc.NodePool("Bullet");
        //初始化N颗子弹
        let url = "prefabs/bullet/bullet_" + index;
        cc.loader.loadRes(url, cc.Prefab, (err, prefab) => {
            if (err) {
                cc.log(err);
            }
            this.bulletPrefab = prefab;
            let initCount = 20;
            for (let i = 0; i < initCount; i++) {
                let bullet: cc.Node = cc.instantiate(this.bulletPrefab);
                this.bulletPool.put(bullet);
            }
        })

    }

    /**
     * 同步当前玩家的所有子弹
     * @param bullets 
     */
    copyBullets(bullets: Array<LBullet>) {
        let heroBullets = this.bullets;
        //逻辑层一定比表现层子弹个数多或者相等
        // if (this.playerId == MGOBE.Player.id) {
        //     if(bullets.length > 0){
        //         cc.log(`逻辑层子弹个数:${bullets.length}`)
        //         cc.log(`表现层子弹个数:${heroBullets.length}`)
        //     }
        // }
        
        //先把所有需要销毁的子弹销毁掉-逻辑层和表现层同步销毁
        for (let i = 0; i < heroBullets.length; i++) {
            let b = bullets[i];
            if (b == undefined) {
                let bulletMgr = heroBullets[i];
                bullets.splice(i, 1);
                heroBullets.splice(i, 1);
                // bulletMgr.destroyBullet();
            }
        }

        if (bullets.length <= 0) return;

        for (let i = 0; i < bullets.length; i++) {
            let b = bullets[i];  //逻辑层子弹
            let hb = this.bullets[i];  //表现层子弹

            if (b == undefined) return;
            if (!hb) { //如果不存在，则新创建一个子弹节点
                let bullet: cc.Node = null;
                if (this.bulletPool.size() > 0) {
                    //传入当前hero的bulletPool对象，以供以后的子弹销毁
                    bullet = this.bulletPool.get(this.bulletPool);
                } else {
                    bullet = cc.instantiate(this.bulletPrefab);
                }
                let bulletMgr: Bullet = bullet.getComponent("Bullet");
                //要注意子弹的朝向
                bulletMgr.initBullet(b.bulletRadian, this.bNomalDegree, this.node.getComponent("Hero"));
                //子弹出生的初始位置为当前插值的坦克位置加上偏移量，掩盖表现层子弹位置的偏差
                bullet.setPosition(b.startPosx + this.node.x, b.startPosy + this.node.y);
                this.mapRoot.addChild(bullet);
                // bulletMgr.updatePosition(b.x, b.y);

                this.bullets.push(bulletMgr);
            } else { //如果存在，则更新子弹位置即可
                // let bulletMgr = hb;
                // bulletMgr.updatePosition(b.x, b.y);
            }
        }



    }

    /**
     * 设置射击状态
     * @param isShooting 
     */
    setIsShooting(isShooting: boolean) {
        // cc.log("正在射击:" + isShooting);
        this.isShooting = isShooting;
    }

    /**
     * 设置旋转弧度
     * @param radian 
     */
    setRotateRadian(radian: number) {
        this.rotateRadian = radian;
    }

    /**
     * 设置移动弧度
     * @param rad 
     */
    setMoveRadian(rad: number) {
        this.moveRadian = rad;
        this.moveDegree = - parseFloat(cc.misc.radiansToDegrees(rad).toFixed(4));
        this.setPlayerRotation(this.moveDegree);
    }

    /**
     * 是否在移动
     * @param is 
     */
    setIsMoving(is: boolean) {
        this.isMoving = is;
    }

    /**
     * 设置车头方向
     * @param degree 
     */
    setPlayerRotation(degree: number) {
        this.player.rotation = degree;
    }

    /**
     * 设置坦克炮头方向
     */
    setWeaponRotation(degree: number) {
        this.weapon.rotation = degree;
    }

    /**
     * 初始化大炮
     * @param index 
     */
    initWeapon(index: number) {
        let url = "/textures/weapon/weapon_" + index;
        cc.loader.loadRes(url, cc.SpriteFrame, (error: Error, spriteFrame: any) => {
            this.weapon.getComponent(cc.Sprite).spriteFrame = spriteFrame;
        })

    }

    /**
     * 初始化车身图片
     * @param index 
     */
    initHeroImg(index: number) {
        let url = "/textures/hero/hero_" + index;
        cc.loader.loadRes(url, cc.SpriteFrame, (error: Error, spriteFrame: any) => {
            if (error) {
                cc.log(error);
            }
            this.player.getComponent(cc.Sprite).spriteFrame = spriteFrame;
        })
    }

    //像素坐标转瓦片坐标
    // getTilePosition(pixelPos) {
    //     let tileSize: cc.Size = this.map.getTileSize();
    //     let x = Math.floor(pixelPos.x / tileSize.width);
    //     let y = Math.floor(pixelPos.y / tileSize.height);
    //     return cc.v2(x, y);
    // }
}
